package com.xqboss.apps.service.sys;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xqboss.apps.constant.RedisKey;
import com.xqboss.apps.domain.sys.SysPopup;
import com.xqboss.apps.dto.system.AppGetPopupListDto;
import com.xqboss.apps.dto.system.GetPopupListDto;
import com.xqboss.apps.enums.mq.AppMqDelayEnum;
import com.xqboss.apps.enums.sys.FileTypeEnum;
import com.xqboss.apps.enums.sys.PopupJumpEnum;
import com.xqboss.apps.mapper.sys.SysPopupMapper;
import com.xqboss.apps.service.aliyun.OssService;
import com.xqboss.common.core.mq.MqSender;
import com.xqboss.common.core.redis.RedisCache;
import com.xqboss.common.exception.ServiceException;
import com.xqboss.common.utils.StringUtils;
import com.xqboss.common.utils.sql.SqlUtil;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
public class SysPopupService extends ServiceImpl<SysPopupMapper, SysPopup> {

    @Lazy
    @Autowired
    private MqSender mqSender;

    @Autowired
    private RedisCache redisCache;
    
    @Autowired
    private OssService ossService;

    /**
     * 添加弹窗
     */
    public void addPopup(SysPopup popup){
        popup.setId(null);
        editPopup(popup);
    }

    /**
     * 获取弹窗详情
     * @param popupId
     * @return
     */
    public SysPopup getPopupDetail(Long popupId){
        SysPopup popup = getById(popupId);
        if (popup == null) {
            throw new ServiceException("弹窗不存在！");
        }
        if(popup.getJumpType() == PopupJumpEnum.H5){
            // 从oss获取详情
            popup.setContent(ossService.getObject(popup.getOssPath()));
        }
        return popup;
    }

    /**
     * 修改弹窗
     * @param popup
     */
    public void editPopup(SysPopup popup){
        // 判断自动上架时间和下架时间
        LocalDateTime now = LocalDateTime.now();
        if(Objects.nonNull(popup.getSaleableTime())){
            if(!now.isBefore(popup.getSaleableTime())){
                throw new ServiceException("上架时间只能为未来的时间！");
            }
        }
        if(Objects.nonNull(popup.getUnsaleableTime())){
            if(!now.isBefore(popup.getUnsaleableTime())){
                throw new ServiceException("下架时间只能为未来的时间！");
            }
        }
        if(Objects.nonNull(popup.getSaleableTime()) && Objects.nonNull(popup.getUnsaleableTime())){
            // 上下架时间都不为空的时候：
            if(!popup.getUnsaleableTime().isAfter(popup.getSaleableTime())){
                throw new ServiceException("下架时间必须在上架时间之后！");
            }
        }
        if(Objects.nonNull(popup.getRegisterTimeStart()) && Objects.nonNull(popup.getRegisterTimeEnd())){
            if(!popup.getRegisterTimeStart().isBefore(popup.getRegisterTimeEnd())){
                throw new ServiceException("注册结束时间必须在开始时间之后！");
            }
        }
        if(popup.getJumpType() == PopupJumpEnum.H5){
//            if(Objects.isNull(popup.getOssPath())){
                // 生成path
                String path = FileTypeEnum.PopupHtml.getPath() + IdUtil.fastSimpleUUID() + ".html";
                popup.setOssPath(path);
//            }
            // 将富文本保存到oss
            String link = ossService.putObject(popup.getOssPath(), popup.getContent());
            popup.setJumpContent(link);
        }
        boolean save;
        if(Objects.isNull(popup.getId())){
            save = save(popup);
        }else{
            save = updateById(popup);
        }
        if(!save){
            throw new ServiceException("操作失败！");
        }
        mqSender.cancelDelay(AppMqDelayEnum.POPUP_MSG_SHOW, popup.getId());
        mqSender.cancelDelay(AppMqDelayEnum.POPUP_MSG_HIDE, popup.getId());
        if(Objects.nonNull(popup.getSaleableTime())){
            mqSender.sendDelay(AppMqDelayEnum.POPUP_MSG_SHOW, popup.getId(), popup.getSaleableTime());
        }
        if(Objects.nonNull(popup.getUnsaleableTime())){
            mqSender.sendDelay(AppMqDelayEnum.POPUP_MSG_HIDE, popup.getId(), popup.getUnsaleableTime());
        }
    }

    /**
     * 弹窗上下架
     * @param id
     * @param saleable
     */
    public void changeSaleable(Long id, Boolean saleable){
        LambdaUpdateWrapper<SysPopup> updateWrapper = new LambdaUpdateWrapper<SysPopup>()
                .set(SysPopup::getSaleable, saleable)
                .eq(SysPopup::getId, id);
        if(saleable){
            updateWrapper.set(SysPopup::getSaleableTime, LocalDateTime.now());
        }else{
            updateWrapper.set(SysPopup::getUnsaleableTime, LocalDateTime.now());
        }
        boolean update = update(updateWrapper);
        if(!update){
            throw new ServiceException("操作失败！");
        }
        if(saleable){
            mqSender.cancelDelay(AppMqDelayEnum.POPUP_MSG_SHOW, id);
        }else{
            mqSender.cancelDelay(AppMqDelayEnum.POPUP_MSG_HIDE, id);
        }
    }

    /**
     * 获取弹窗列表
     * @param dto
     * @return
     */
    public List<SysPopup> getPopupList(GetPopupListDto dto) {
        LambdaQueryWrapper<SysPopup> queryWrapper = new LambdaQueryWrapper<>();
        if(dto.getSaleable() != null){
            queryWrapper.eq(SysPopup::getSaleable, dto.getSaleable());
        }
        if(dto.getType() != null){
            queryWrapper.eq(SysPopup::getType, dto.getType());
        }
        if(dto.getPosition() != null){
            queryWrapper.eq(SysPopup::getPosition, dto.getPosition());
        }
        if(StringUtils.isNotEmpty(dto.getSearch())){
            queryWrapper.like(SysPopup::getTitle, dto.getSearch());
        }
        queryWrapper.orderByDesc(SysPopup::getId);
        return list(queryWrapper);
    }

    /**
     * 用户获取上架的弹窗列表
     * @param params
     * @return
     */
    public List<SysPopup> getSaleablePopupList(AppGetPopupListDto params) {
        List<SysPopup> list = baseMapper.getUserPopupList(params);
        return list;
    }

    /**
     * 弹窗自动上架
     * @param id
     */
    public void autoSaleable(long id) {
        SysPopup popup = getById(id);
        if(Objects.isNull(popup)){
            throw new ServiceException("弹窗不存在！");
        }
        if(BooleanUtils.isNotTrue(popup.getSaleable())){
            //还没有上架， 判断是否达到上架时间
            if(Objects.nonNull(popup.getSaleableTime())){
                if(LocalDateTime.now().isBefore(popup.getSaleableTime())){
                    throw new ServiceException("还未到达上架时间！");
                }else{
                    //到达上架时间
                    if(Objects.nonNull(popup.getUnsaleableTime())){
                        if(LocalDateTime.now().isAfter(popup.getUnsaleableTime())){
                            throw new ServiceException("超过下架时间！");
                        }
                    }
                }
            }else{
                throw new ServiceException("未设置自动上架时间！");
            }
        }else{
            throw new ServiceException("重复操作：弹窗已上架！");
        }
        boolean update = update(new LambdaUpdateWrapper<SysPopup>()
                .set(SysPopup::getSaleable, true)
                .eq(SysPopup::getId, id));
        if(!update){
            throw new ServiceException("上架失败！");
        }
    }

    /**
     * 弹窗自动下架
     * @param id
     */
    public void autoUnSaleable(long id) {
        SysPopup popup = getById(id);
        if(Objects.isNull(popup)){
            throw new ServiceException("弹窗不存在！");
        }
        if(BooleanUtils.isNotFalse(popup.getSaleable())){
            //还没有下架， 判断是否达到下架时间
            if(Objects.nonNull(popup.getUnsaleableTime())){
                if(LocalDateTime.now().isBefore(popup.getUnsaleableTime())){
                    throw new ServiceException("还未到达下架时间！");
                }
            }else{
                throw new ServiceException("未设置自动下架时间！");
            }
        }else{
            throw new ServiceException("重复操作：弹窗已下架！");
        }
        boolean update = update(new LambdaUpdateWrapper<SysPopup>()
                .set(SysPopup::getSaleable, false)
                .eq(SysPopup::getId, id));
        if(!update){
            throw new ServiceException("下架失败！");
        }
    }
}
